package vload

import (
	"fmt"
	"reflect"
)

// callGetter 调用值获取器
func callGetter(getter interface{}, keyList []interface{}) (map[interface{}]interface{}, error) {
	// 使用反射调用原始的值获取器
	fn := reflect.ValueOf(getter)
	fnType := fn.Type()

	// 检查函数签名
	if fnType.Kind() != reflect.Func {
		return nil, fmt.Errorf("getter must be a function")
	}

	// 准备参数
	paramType := fnType.In(0)
	var keysVal reflect.Value

	// 处理不同类型的切片
	switch paramType.Kind() {
	case reflect.Slice:
		elemType := paramType.Elem()
		keysVal = reflect.MakeSlice(paramType, len(keyList), len(keyList))
		for i, key := range keyList {
			keyVal := reflect.ValueOf(key)
			if keyVal.Type() != elemType {
				return nil, fmt.Errorf("key type mismatch: expected %v, got %v", elemType, keyVal.Type())
			}
			keysVal.Index(i).Set(keyVal)
		}
	default:
		return nil, fmt.Errorf("unsupported parameter type: %v", paramType)
	}

	// 调用函数
	result := fn.Call([]reflect.Value{keysVal})

	// 检查返回值
	if len(result) != 2 {
		return nil, fmt.Errorf("invalid getter function: must return (map, error)")
	}

	// 检查错误
	errVal := result[1]
	if !errVal.IsNil() {
		return nil, errVal.Interface().(error)
	}

	// 转换结果
	resultMap := result[0]
	if resultMap.Kind() != reflect.Map {
		return nil, fmt.Errorf("first return value must be a map")
	}

	convertedMap := make(map[interface{}]interface{})
	mapKeys := resultMap.MapKeys()

	for _, key := range mapKeys {
		convertedMap[key.Interface()] = resultMap.MapIndex(key).Interface()
	}

	return convertedMap, nil
}

// collectKeys 收集键值
func (l *Loader) collectKeys(val reflect.Value, keysByGroup map[string]map[interface{}]struct{}, validPairsByGroup map[string][]Pair) {
	// 处理切片和单个结构体
	var values []reflect.Value
	switch val.Kind() {
	case reflect.Slice:
		values = make([]reflect.Value, val.Len())
		for i := 0; i < val.Len(); i++ {
			values[i] = val.Index(i)
		}
	case reflect.Struct:
		values = []reflect.Value{val}
	default:
		return
	}

	for group, pairs := range validPairsByGroup {
		if _, ok := keysByGroup[group]; !ok {
			keysByGroup[group] = make(map[interface{}]struct{})
		}
		for _, pair := range pairs {
			for _, v := range values {
				sourceField := v.FieldByName(pair.SourceField)
				if !isZeroValue(sourceField) {
					keysByGroup[group][sourceField.Interface()] = struct{}{}
				}
			}
		}
	}
}

// fillValues 填充值
func (l *Loader) fillValues(val reflect.Value, valueMap map[interface{}]interface{}, validPairs []Pair) {
	for _, pair := range validPairs {
		sourceField := val.FieldByName(pair.SourceField)
		if !isZeroValue(sourceField) {
			if value, ok := valueMap[sourceField.Interface()]; ok {
				targetField := val.FieldByName(pair.TargetField)
				targetField.Set(reflect.ValueOf(value))
			}
		}
	}
}

// isZeroValue checks if a reflect.Value is considered zero
func isZeroValue(val reflect.Value) bool {
	// Check for zero based on different types
	switch val.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return val.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return val.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return val.Float() == 0
	case reflect.String:
		return val.String() == ""
	case reflect.Ptr, reflect.Interface, reflect.Slice, reflect.Map:
		return val.IsNil()
	case reflect.Bool:
		return false
	case reflect.Struct:
		return val.Interface() == reflect.Zero(val.Type()).Interface()
	default:
		return false
	}
}

// validatePairs checks if the specified pairs are valid for the given type
func validatePairs(val reflect.Type, pairs []Pair) error {
	for _, pair := range pairs {
		// Check if source field exists
		_, sourceExists := val.FieldByName(pair.SourceField)
		if !sourceExists {
			return fmt.Errorf("source field %s does not exist", pair.SourceField)
		}

		// Check if target field exists
		_, targetExists := val.FieldByName(pair.TargetField)
		if !targetExists {
			return fmt.Errorf("target field %s does not exist", pair.TargetField)
		}
	}
	return nil
}
